class Observer {
  constructor () {
    // 店员的记事本
    this.messageList = {}
  }

  // 需要在原型上书写三个方法
  // 添加
  $on (type, fn) {
    // type 就是要订阅的名称
    // fn 就是要订阅的函数
    // 判断一下, 我的 messageList 内是否有 type 所代表的这一条记录
    // this.messageList[type] 如果有一定是一个 数组
    // this.messageList[type] 如果没有就是 undefined
    this.messageList[type] = this.messageList[type] || []

    // 代码执行到这里, 说明 this.messageList[type] 一定是一个数组
    // 只需要把相对应的 fn 存储在这个数组内即可
    this.messageList[type].push(fn)
  }

  // 删除
  $off (type, fn) {
    // 1. 如果根本没有 type 所代表的这一条记录, 什么也不需要执行
    // 判断 this.messageList 内是否存在 type 所代表的记录
    // this.messageList[type] 的值
    //   要么是一个数组
    //   要么是一个 undefined
    if (!this.messageList[type]) {
      // 代码能执行到这里, 说明 !this.messageList[type] 是 true
      // 说明 this.messageList[type] 是 false
      // this.messageList[type] 要么是 数组, 要么是 undefined
      // 如果是数组, 那么就是 true
      // 如果是 undefined, 那么就是 false
      // 代码能执行到这里, 说明 this.messageList[type] 是 undefined
      return
    }

    // 代码来到这里, 说明 this.messageList[type] 存在, 是一个数组, 我有当前这个记录
    // 判断 fn 参数, 有可能传递, 也有可能不传递
    // fn 要么是 undefined 要么是一个 函数
    if (!fn) {
      // 代码能执行到这里, 说明 fn 是一个 undefined
      // 表示没有传递指定要删除的事件处理函数, 那么直接删除整条记录
      // 从 this.messageList 对象内删除 type 所代表的这一条记录
      // 对象的删除语法
      //   delete 对象名['键名']
      //   delete 对象名.键名
      delete this.messageList[type]
      return
    }

    // 代码执行到这里, 说明 fn 是一个函数, 表示有要删除的指定的事件处理函数
    // 从该记录内, 把指定的这一条事件处理函数删除
    this.messageList[type] = this.messageList[type].filter(item => item !== fn)
  }

  // 发布
  $emit (type, ...data) {
    // data 就是本次需要携带的信息, 利用扩展运算符把所有需要传递的信息放在了一个数组内
    // 判断 this.messageList 内是否存在 type 代表的这一条记录
    // 如果不存在, 什么也不需要执行
    if (!this.messageList[type]) return

    // 代码执行到这里, 说明 该记录存在
    // 你要让每一个记录下来的函数都执行一遍
    this.messageList[type].forEach(item => {
      // item 就是数组内的每一项, 其实就是每一个记录的函数
      // 给出信息的时候进行一下判断, 如果只有一个, 那么我直接给你数据, 如果有多个按照数组方式给你
      item(data.length === 1 ? data[0] : data)
    })
  }
}

export default new Observer()